/*
 VideoLoader
 
 Copyright (c) 2007-2008 Mary Jane Soft - Marlon J. Manrique
 	
 http://mjs.darkgreenmedia.com
 http://marlonj.darkgreenmedia.com
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 $Id: VideoLoader.pde 375 2008-02-28 14:39:27Z marlonj $
 	
*/

/**
 * Data structure to hold Video Information
 */
class Video
{
  String url; // The rtsp address of the video
  String thumb; // The url address of the thumbnail
  String title; // The title of the video
  String runtime; // The duration of the video
}

/**
 * The YouTube information loader.
 *
 * This class retrives the search list of videos using the website 
 * http://m.youtube.com
 */
class VideoLoader
{
  // Parent MIDlet
  PMIDlet pMIDlet;

  // Network cliente to retrive search results
  MClient mClient;
  MRequest mRequest;

  // XML parser to grab search results 
  MXMLParser mXmlParser;

  // Warning already retrive 
  boolean warning = true;

  // Server connectivity
  String server = "m.youtube.com";
  String[] cookies;
  String[] params = { 
    "q"       };
  String[] values = { 
    " "       };  

  // Doc Marks
  boolean videoMark;
  boolean titleMark;
  boolean runtimeMark;

  // Current Information
  String videoURL;
  String videoThumb;
  String videoTitle;
  String videoRuntime;

  // Text to search
  String searchText = "";

  // Video Information
  Video[] videos;
  int pageVideos = 10;
  int videoCounter;

  // YouTube Logo
  PImage youtubeImage;  

  /**
   * Create a VideoLoder with this parent
   *
   * @param pMIDlet The parent MIDlet
   */
  VideoLoader(PMIDlet pMIDlet)
  {
    // Init basic elements
    this.pMIDlet = pMIDlet;    
    softkey("Search");    
    youtubeImage = loadImage("youtubelogo.png");    

    // Create result parser
    mXmlParser = new MXMLParser(pMIDlet);  
    mClient = new MClient(pMIDlet,server);

    // Create array for video information
    videos = new Video[pageVideos]; 
  }

  /**
   * Draw a background image
   */
  void draw()
  {
    // Clear the scene and move to the center of the screen
    background(0);
    translate(width/2,height/2);    

    // Draw the background image
    image(youtubeImage,-youtubeImage.width/2,-youtubeImage.height/2);
  }

  /**
   * Check the sofkey
   */
  void softkeyPressed(String label)
  {
    // If the user press the Search softkey 
    if(label.equals("Search"))
    {   
      // Get the search text from the user
      String tmpText = textInput("Search",searchText,100);

      // If no cancel start searching
      if(tmpText != null)
      {
        // Update the search text
        searchText = tmpText; 
        searchVideos(searchText);
      }
    }
  }

  /**
   * Check user interaccion 
   */
  void keyPressed()
  {
    // If another component already consume the key 
    // Do nothing
    if(keyEventConsumed)
      return;

    // Check keys 
    switch(keyCode)
    {
      // Play the current selected video
    case FIRE : 
      playVideo();      
      break;
      // If navigation keys, update current video info
    case LEFT : 
    case RIGHT :
      updateVideoInfo();
      break;	
    }
  }

  /**
   * Start the search 
   *
   * @param searchText Search the videos associated with the text
   */
  void searchVideos(String searchText)
  {
    // If the cookies are availables
    if(!warning)
    {
      // Set the search text
      values[0] = searchText; 

      // Clear any previous search 
      message = "Searching ...";
      imageBrowser.clear();      
      videoCounter = 0;
      foot = "";
      videoMark = false;
      titleMark = false;
      runtimeMark = false;
      videoURL = null;
      videoTitle = null;
      videoThumb = null;
      videoRuntime = null;      

      // Create the search request and set the cookies
      mRequest = (MRequest) mClient.GET("/results",params,values);    
      mRequest.cookies(cookies);
    }
    // If the cookies are not available, read it    
    else
    {
      // Create the cookie request
      mRequest = (MRequest) mClient.GET("/?warned=yes");
      message = "Connecting ...";
    }      
  }

  /**
   * Listen library events
   */
  void libraryEvent(Object library, int event, Object data)
  {
    // The network request
    if(library == mRequest)
    {
      switch(event)
      {
      case PRequest.EVENT_CONNECTED :
        // Read the cookies values
        if(warning)
          mRequest.readBytes();
        // Parse result in the xhtml page
        else
          mXmlParser.start(mRequest);
        break;
      case PRequest.EVENT_DONE : 
        // If no cookies, grab it
        if(warning)
        {
          // Get cookies
          cookies = mRequest.cookies();
          warning = false;

          // Perform the pending search 
          searchVideos(searchText);
        }          
        break;
      }
    }
    else if(library == mXmlParser)
    {
      switch(event)
      {
        // Check the video tags 
      case XMLParser.EVENT_TAG_START :
        // All the parts are mark with div 
        if(data.equals("div"))
        {
          // Ge the class of the tag
          String divClass = mXmlParser.attribute("class");

          // If the element have a class 
          if(divClass != null)          
            // The tag is the video entry, add previous video and mark 
            if(divClass.equals("vEntry padL3"))
            {
              if(videoMark)
                addVideo();
              else
                videoMark = true;

              // Draw a message
              message = "Found: " + (videoCounter+1);
            }
          // Mark the next element like title 
            else if(divClass.equals("vTitle"))
              titleMark = true;
          // Mark the next element like runtime
            else if(divClass.equals("vRuntime"))
              runtimeMark = true;
          // If tag is vPager padL3, no more interesting information
            else if(divClass.equals("vPager padL3"))
            {
              // Stop parsing and close the connection
              mXmlParser.stop();              
              mRequest.close();

              // Add the last video of the list if any
              // and start retriving the imagesv
              if(videoMark)
              {
                addVideo();
                loadImages();                      
              }
              // Show a message if no videos
              else
                message = "No Results";
            }
        }        
        // If an ref tag is next and the video entry is available
        // and no previous ref was found, grab it                   
        else if(data.equals("a"))
        {
          if(videoMark && videoURL == null)
            videoURL = mXmlParser.attribute("href");
        }
        // If an image tags is next and the video entry is available
        // and no previous ref was found, grab it             
        else if(data.equals("img"))
          if(videoMark && videoThumb == null)
            videoThumb = mXmlParser.attribute("src");
        break;

        // Text elements 
      case XMLParser.EVENT_TEXT :
        // Get the title if a mark is available and no previous 
        if(titleMark && videoTitle == null)
          videoTitle = (String) data;
        // Get the runtime if a mark is available and no previous
        else if(runtimeMark && videoRuntime == null)
          videoRuntime = ((String) data).trim();
        break;
      }
    }  
  }

  /**
   * Add the current video data to the array
   */
  void addVideo()
  {
    // Create a video object with the current information
    Video video = new Video();
    video.url = videoURL;
    video.title = videoTitle;
    video.runtime = videoRuntime;
    video.thumb = videoThumb;

    // Reset marks 
    titleMark = false;
    runtimeMark = false;
    videoURL = null;
    videoTitle = null;
    videoThumb = null;
    videoRuntime = null;

    // Add the video
    videos[videoCounter++] = video;
  }

  /**
   * Load the images of the thumbnails of the videos found
   */
  void loadImages()
  {
    // Create a list of urls 
    String[] urls = new String[videoCounter];

    // Retrieve each video thumbnail
    for(int i=0; i<videoCounter; i++)
      urls[i] = videos[i].thumb;

    // Download and show the images 
    imageBrowser.downloadImages(urls);

    // Update the current video information
    updateVideoInfo();
  }  

  /**
   * Play the video selected inf the browser
   */
  void playVideo()
  {
    // If a video is selected and the player is closed 
    // play the video 
    if(imageBrowser.currentImage != -1 && 
      videoPlayer.state == VideoPlayer.CLOSED)
    {
      String url = videos[imageBrowser.currentImage].url;
      videoPlayer.play(url);

      // Consume the key event
      keyEventConsumed = true;
    }
  }

  /**
   * Update the screen information with the current selected video info
   */
  void updateVideoInfo()
  {
    // Get the current index
    int index = imageBrowser.currentImage;

    // if a video is selected
    if(index != -1)
      // Update foot information
      foot = videos[index].title 
        + " " + videos[index].runtime;
  }
}
